package com.example.springstack.mybatisplus.init;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.springstack.mybatisplus.entity.Parameters;
import com.example.springstack.mybatisplus.service.ParametersService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;


import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

/**
 * @author qiangfanghao
 * @date
 * mysql sql语句初始化
 * mysql表无法插入中文字符,需要手动设置字符集为 utf8
 */
@Slf4j
@Configuration
public class UpdateSqlInit implements InitializingBean {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private ParametersService parametersService;

    /**
     *   获取版本号
     */
    private final String initFilePath = "/init/init.sql";
    /**
     * sql初始化
     */
    private String sql = "init/init.sql";

    private List<String> lineList = new ArrayList<String>();

    @Override
    public void afterPropertiesSet() throws Exception {


        try{
            log.debug("初始化sql开始");
            //获取sql文件终端版本号
            String version = getVersion();
            if(StringUtils.isBlank(version)){
                throw new RuntimeException("版本号为空初始化失败");
            }
            //初始化sql
            initialize(version);



        }catch(Exception e){
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }


    /**
     * 初始化sql
     * @param version
     */
    private void initialize(String version){

        //获取到 初始化参数中
        QueryWrapper<Parameters> parametersQueryWrapper = new QueryWrapper<>();
        parametersQueryWrapper.eq("name","dbupdate");
        Parameters parameters = parametersService.getOne(parametersQueryWrapper);

        if (BeanUtil.isNotEmpty(parameters)){
            String value = parameters.getValue();
            //如果 value与 version 不等 则进行初始化
            if (!value.equalsIgnoreCase(version)){
                sqlInitialize();
                //更新项目版本号
                parameters.setValue(version);
                this.parametersService.saveOrUpdate(parameters);


            }else {
                log.debug("版本号检索成功,不进行Sql初始化");
            }
        }else {
            //更新sql语句
            sqlInitialize();

            //设置系统参数
            Parameters tempParameter = new Parameters();
            tempParameter.setName("dbupdate");
            tempParameter.setType("init");
            tempParameter.setValue(version);
            tempParameter.setDescription("项目初始号sql版本号");

            this.parametersService.save(tempParameter);
        }
    }

    /**
     * 初始化 .sql文件内容
     */
    private void sqlInitialize(){
        try {
            //根据sql文件进行初始化
            DataSource ds = applicationContext.getBean(DataSource.class);
            Connection con = ds.getConnection();
            ScriptRunner sr = new ScriptRunner(con);
            sr.runScript(Resources.getResourceAsReader(sql));


            log.debug("该版本数据库升级sql初始化完成标记.");

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    /**
     * 获取 系统参数Init版本号
     * @return
     */
    private String getVersion(){
        List<String> list = getLineList();
        if(list.isEmpty()){
            return null;
        }
        String line = list.get(0).trim();
        return line.substring("--".length()).trim();
    }

    private List<String> getLineList() {
        try {
            if(lineList.isEmpty()){
                //根据文件路径获取input流 获取到文件内容 springboot jar包中 无法根据classpath获取
                ClassPathResource res = new ClassPathResource(initFilePath);
                InputStream inputStream = res.getInputStream();
                if(!res.exists()){
                    log.error("找不到系统初始化文件:{}", "init.sql");
                    throw new RuntimeException();
                }

                lineList = IOUtils.readLines(inputStream,"utf-8");
                inputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return lineList;
    }
}
